#include "GltfLoader.h"

#pragma warning(push)
#pragma warning(disable : 4996)
#define CGLTF_IMPLEMENTATION
#include "cgltf.h"
#pragma warning(pop)


#include "Containers/Vector.h"

TVector<SVertexGroup> CGltfLoader::LoadVertexGroups(const SPath&  FilePath,float UnitScale)
{
    // load file
    TVector<uint8_t> Data;
    {
        std::ifstream File(FilePath.GetLowLevel(), std::ios::ate | std::ios::binary);

        if(!File.is_open())
        {
            //read file faild
            assert(false&&"Cant open file!");
        }
        auto FileSize = File.tellg();
        Data.Resize(FileSize);
        File.seekg(0);
        File.read((char*)Data.Data(), FileSize);
    }

    cgltf_options options = {};
    cgltf_data* data = NULL;
    cgltf_result result = cgltf_parse(&options, Data.Data(), Data.Num(), &data);

    if (result != cgltf_result_success)
    {
        return TVector<SVertexGroup>();    
    }

    cgltf_load_buffers(&options,data,nullptr);
    
    //read vertex
    if(data->meshes_count<=0)
    {
        return TVector<SVertexGroup>();
    }

    TVector<SVertexGroup> Ret;
    Ret.Resize(data->meshes[0].primitives_count);

    for(int PrimitiveIndex=0;PrimitiveIndex<Ret.Num();PrimitiveIndex++)
    {
        cgltf_attribute* PositionAttribute=nullptr;
        cgltf_attribute* UVAttribute=nullptr;
        cgltf_attribute* NormalAttribute=nullptr;
        for(int i=0; i< data->meshes[0].primitives[PrimitiveIndex].attributes_count;i++)
        {
            cgltf_attribute* attribute=data->meshes[0].primitives[PrimitiveIndex].attributes+i;
            if(0==strcmp("POSITION",data->meshes[0].primitives[PrimitiveIndex].attributes[i].name))
            {
                PositionAttribute=data->meshes[0].primitives[PrimitiveIndex].attributes+i;
                continue;
            }
            else if(0==strcmp("NORMAL",data->meshes[0].primitives[PrimitiveIndex].attributes[i].name))
            {
                NormalAttribute=data->meshes[0].primitives[PrimitiveIndex].attributes+i;
                continue;                
            }
            else if(0==strcmp("TEXCOORD_0",data->meshes[0].primitives[PrimitiveIndex].attributes[i].name))
            {
                UVAttribute=data->meshes[0].primitives[PrimitiveIndex].attributes+i;
                continue;                
            }
        }

        cgltf_accessor* Indices=data->meshes[0].primitives[PrimitiveIndex].indices;

        TVector<cgltf_uint> IndiceData;
        IndiceData.Resize(Indices->count);
        for(int Index=0;Index< Indices->count; Index++)
        {
            cgltf_accessor_read_uint(Indices,Index,IndiceData.Data()+Index,1);
        }

        TVector<cgltf_float> PositionData;
        PositionData.Resize(3*PositionAttribute->data->count);
        for(int VertexIndex=0;VertexIndex< PositionAttribute->data->count; VertexIndex++)
        {
            cgltf_accessor_read_float(PositionAttribute->data,VertexIndex,PositionData.Data()+VertexIndex*3,3);
        }

        TVector<cgltf_float> UVData;
        UVData.Resize(2*UVAttribute->data->count);
        for(int VertexIndex=0;VertexIndex< UVAttribute->data->count; VertexIndex++)
        {
            cgltf_accessor_read_float(UVAttribute->data,VertexIndex,UVData.Data()+VertexIndex*2,2);
        }


        TVector<cgltf_float> NormalData;
        NormalData.Resize(3*NormalAttribute->data->count);
        for(int VertexIndex=0;VertexIndex< NormalAttribute->data->count; VertexIndex++)
        {
            cgltf_accessor_read_float(NormalAttribute->data,VertexIndex,NormalData.Data()+VertexIndex*3,3);
        }

        //TVector<SVertex> Vertice;
        Ret[PrimitiveIndex].Vertice.Resize(PositionData.Num()/3);
        for(int VertexIndex=0;VertexIndex< PositionData.Num()/3; VertexIndex++)
        {
            Ret[PrimitiveIndex].Vertice[VertexIndex].Position=SVec3(PositionData[VertexIndex*3]*UnitScale,
                PositionData[VertexIndex*3+1]*UnitScale,
                PositionData[VertexIndex*3+2]*UnitScale);
            Ret[PrimitiveIndex].Vertice[VertexIndex].Normal=SVec3(NormalData[VertexIndex*3],NormalData[VertexIndex*3+1],NormalData[VertexIndex*3+2]);
            Ret[PrimitiveIndex].Vertice[VertexIndex].UV=SVec2(UVData[VertexIndex*2],UVData[VertexIndex*2+1]);
        }

        Ret[PrimitiveIndex].Indices.Resize(IndiceData.Num());
        for(int Index=0;Index<IndiceData.Num();Index++)
        {
            Ret[PrimitiveIndex].Indices[Index]=IndiceData[Index];
        }
    }

    cgltf_free(data);


    return Ret;
 

}